from collections import namedtuple
from flask import request, g, current_app
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from functools import wraps

from app.libs.error_code import AuthFailed, NotFound

User = namedtuple('User', ['uid', 'scope'])


# def login_required(func):
#     @wraps(func)
#     def wrapper(*args, **kwargs):
#
#         password = request.args.get('password')
#         if not password:
#             password = request.json['password']
#             if not password:
#                 AuthFailed(msg='请输入密码', error_code=1099)
#         try:
#             UserModel.query.filter_by(password=password).first_or_404()
#         except Exception:
#             raise AuthFailed(msg='没有权限', error_code=1099)
#         return func(*args, **kwargs)
#
#     return wrapper


def create_token(id):
    """
    生成token
    :param api_user: 用户id
    :return: token
    """

    # 第一步设置参数内部的私钥，这里这里写在共用的配置信息，如果是测试可以写死
    # 第二部 参数是有效期（秒）
    s = Serializer(secret_key=current_app.config.get('SECRET_KEY'), expires_in=60 * 60 * 24 * 30)

    # 接受用户的id转换与编码
    token = s.dumps(id).decode('ascii')
    return token


def verify_token(token):
    """
    校验token
    :param token:
    :return: 用户信息 or None
    """

    # 参数为私钥，跟create_token的私钥保持一致
    s = Serializer(secret_key=[current_app.config.get('SECRET_KEY')])
    try:
        # 转换为字典
        data = s.loads(token)
    except Exception:
        raise AuthFailed()
    return data


def login_required(func):
    """
    装饰器 验证请求是必须带有token 判断用户是否登陆
    :param func:
    :return: func
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            # 在请求头拿到token
            token = request.headers['Authorization']
        except Exception:
            # 这里的code写一个文件统一管理。后期再来做
            raise NotFound(msg="请先登录")
        user = verify_token(token)
        g.user = user

        return func(*args, **kwargs)

    return wrapper
